home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / dbdoc.zip / DBFDOC.C < prev    next >
C/C++ Source or Header  |  1991-12-08  |  8KB  |  196 lines

  1. /*    Somerset Data Systems, Inc.  (908) 766-5845                           */
  2. /*    Version 1.2     April 6, 1991                                         */
  3. /*    Programmer:     Jay Parsons                                           */
  4.  
  5. /*  Note:                                                                   */
  6.  
  7. /****************************************************************************/
  8.  
  9. #include <ctype.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12.  
  13. /****************************************************************************/
  14. /*                          definitions                                     */
  15. /****************************************************************************/
  16.  
  17. /****                      ****  values  ****                            ****/
  18.  
  19. #define HEADLEN       32            /* sizeof ( mainhead or thisfield )     */
  20. #define MEMOLEN       10            /* length of memo field in .dbf         */
  21. #define DBFTYPE        3            /* value of bits 0 and 1 if .dbf        */
  22. #define EOH         0x0D            /* end-of-header marker in .dbf file    */
  23.  
  24. /****                     ****  data types  ****                         ****/
  25.  
  26. typedef unsigned long ulong;        /* just an abbreviation                 */
  27.  
  28. extern char file_name[], message[], tempbuff[];
  29.  
  30. /*  first 32 bytes of a .dbf file   */
  31.  
  32. typedef struct
  33. {
  34.     unsigned            dbf:2;      /*  both 1 for dBASE III or IV .dbf     */
  35.     unsigned               :1;
  36.     unsigned         db4dbt:1;      /*  1 if a dBASE IV-type .dbt exists    */
  37.     unsigned               :3;
  38.     unsigned         anydbt:1;      /*  1 if any .dbt exists                */
  39.     char filedate[3];               /*  date, YYMMDD, binary. YY=year-1900  */
  40.     ulong records;                  /*  records in the file                 */
  41.     unsigned headerlen;             /*  bytes in the header                 */
  42.     unsigned recordlen;             /*  bytes in a record                   */
  43.     int rsrvd1;
  44.     char incompleteflag;            /*  01 if incomplete, else 00           */
  45.     char encryptflag;               /*  01 if encrypted, else 00            */
  46.     char rsrvd2[12];                /*  for LAN use                         */
  47.     char mdxflag;                   /*  01 if production .mdx, else 00      */
  48.     char rsrvd3[3];
  49. } dbfheader;
  50.  
  51. /*  field descriptor of a .dbf file         */
  52.  
  53. typedef struct
  54. {
  55.     char fname[11];                 /*  field name, in capitals, null filled*/
  56.     char ftype;                     /*  field type, C, D, F, L, M or N      */
  57.     char rsrvd4[4];                 /*  used in memvars, not in files.      */
  58.     unsigned char flength;          /*  field length                        */
  59.     unsigned char decimals;         /*  number of decimal places            */
  60.     int rsrvd5;
  61.     char workarea;
  62.     char rsrvd6[10];
  63.     char mdxfield;                  /* 01 if tag field in production .mdx   */
  64. } descriptor;
  65.  
  66. /****              ****  function prototypes  ****                       ****/
  67.  
  68. int dbfdoc ( char *filespec );
  69.  
  70. FILE * dbfopen ( char *filespec, dbfheader *buffptr );
  71.  
  72. int dbfield_off ( FILE *file, char *ourfield, descriptor *buf );
  73.  
  74. /****************************************************************************/
  75. /*                              dbfdoc                                      */
  76. /*  Principal routine of this module.  Reads and returns the structure      */
  77. /*  of the file of the name passed.                                         */
  78. /*  Returns:                                                                */
  79. /*      0 if successful, 1 if any error occurs.                             */
  80. /*                                                                          */
  81. /*      This routine creates two buffers for .dbf header information.       */
  82. /*      It then calls dbfopen() to open the file, test for it being a .dbf  */
  83. /*  type and place the main header in its buffer.                           */
  84. /****************************************************************************/
  85.  
  86. int dbfdoc ( char *file_name )
  87. {
  88.     FILE *dbffile;
  89.     dbfheader mainhead;
  90.     descriptor thisfield;
  91.      int field, fields, err;
  92.  
  93. /*  open file and check for .dbf type       */
  94.  
  95. /* must close it if opened, else not        */
  96.                                               
  97.     if ( ( dbffile = dbfopen( file_name, &mainhead ) ) == NULL )
  98.      {
  99.           sprintf( message, "Can't open file %s.", file_name );
  100.           return 1;
  101.      }
  102.     sprintf( message, "Structure of %s", strupr( file_name ) );
  103.     printit( 0 );
  104.      sprintf( message, "%d records, last changed ",  ( int ) mainhead.records );
  105.      sprintf ( tempbuff, "%02d/", mainhead.filedate[1] );
  106.      strcat( message, tempbuff );
  107.      sprintf ( tempbuff, "%02d/", mainhead.filedate[2] );
  108.      strcat( message, tempbuff );
  109.      sprintf ( tempbuff, "%d", mainhead.filedate[0] + 1900 );
  110.      strcat( message, tempbuff );
  111.      printit( 0 );
  112.      strcpy( message, "Field    Type  Len  Dec" );
  113.      printit( 0 );
  114.  
  115. /*  do it field by field.  We are at byte 32 of file  */
  116.  
  117.      fields = ( mainhead.headerlen - 33 ) / 32;
  118.      for ( field = 1; field <= fields; field++ )
  119.      {
  120.           err = fread( &thisfield, HEADLEN, 1, dbffile ) - 1;
  121.           if ( err )
  122.                 break;
  123.           sprintf( message, "%-11s", thisfield.fname );
  124.           strcat( message, " " );
  125.           *tempbuff = thisfield.ftype;
  126.           *( tempbuff + 1 ) = '\0';
  127.           strcat( message, tempbuff );
  128.           sprintf( tempbuff, "  %3d   %2d", thisfield.flength, thisfield.decimals );
  129.           strcat( message, tempbuff );
  130.           printit( 0 );
  131.      }
  132.  
  133.     fclose( dbffile );
  134.     return err;
  135. }
  136.  
  137. /****************************************************************************/
  138. /*                              dbfopen                                     */
  139. /*      Routine to open .dbf file.                                          */
  140. /*  Parameters:                                                             */
  141. /*      char *filespec  -- pointer to spec of file to open                  */
  142. /*      dbfheader *buf  -- pointer to dbfheader structure                   */
  143. /*  Returns:                                                                */
  144. /*      Pointer to C file control structure (to NULL if error)              */
  145. /*  Side effects:                                                           */
  146. /*      Opens file and moves pointer to byte 32; fills buffer at buf with   */
  147. /*  first 32 bytes of file.  Closes file on error.                          */
  148. /****************************************************************************/
  149.  
  150. FILE *dbfopen( char *filespec, dbfheader *buf )
  151. {
  152.     FILE *file;
  153.     char *endmark;
  154.  
  155.     if ( ( file = fopen( filespec, "rb" ) ) == NULL )
  156.     return NULL;                            /* can't open .dbf              */
  157.  
  158. /* read the first 32 bytes into buffer      */
  159.  
  160.     if ( fread( buf, HEADLEN, 1, file ) != 1 )
  161.     {
  162.         fclose( file );
  163.         return NULL;                        /* can't read 32 bytes          */
  164.     }
  165.  
  166. /* check first byte to be sure .dbf type                                    */
  167.  
  168.     if ( buf->dbf != DBFTYPE )
  169.     {
  170.         fclose( file );
  171.         return NULL;                        /* not a .dbf file              */
  172.     }
  173.  
  174. /* check last byte of header                */
  175.  
  176.     if ( fseek( file, buf->headerlen - 1, SEEK_SET ) != 0 )
  177.     {
  178.         fclose( file );
  179.         return NULL;                        /* header corrupted             */
  180.     }
  181.     if ( fread( endmark, 1, 1, file ) != 1 )
  182.     {
  183.         fclose( file );
  184.         return NULL;                        /* can't read end of header     */
  185.     }
  186.     if ( *endmark != EOH )
  187.     {
  188.         fclose( file );
  189.         return NULL;                        /* no 0Dh at end of header      */
  190.     }
  191.     fseek( file, HEADLEN, SEEK_SET );
  192.     return file;
  193. }
  194.  
  195. /*   EOF  */
  196.